package transportServer

import (
	"errors"
	"fmt"
	"gitee.com/jjawesomejj/awesome-util/helper/commonhelper"
	WsServer "gitee.com/jjawesomejj/awesomehttp/system/wsServer"
	"github.com/gorilla/websocket"
	"strconv"
	"sync"
)

type TransportServer struct {
	connectionMap  sync.Map
	initConnection sync.Map
}
type InitMsg struct {
	Command string `json:"command"`
	Sid     string `json:"sid"`
}

type TransportMsg struct {
	Command    string `json:"command"`
	TargetSid  string `json:"target_sid"`
	Payload    []byte `json:"payload"`
	IsFinish   bool   `json:"is_finish"` //结束回环
	RequestSid string `json:"request_sid"`
}

type CommandMsg struct {
	Command string `json:"command"`
}

type ClientMsgSendToTun struct {
	Command  string `json:"command"`
	Payload  []byte `json:"payload"`
	SrcSid   string `json:"src_sid"`
	IsFinish bool   `json:"is_finish"`
}

const COMMAND_INIT = "init"

const COMMAND_TRANSPORT = "transport"

const COMMAND_SEND_TO_TUN = "send_to_tun"

func (transportServer *TransportServer) StartTranPortServer(listenPort int) {
	server := WsServer.WsServer{}
	server.OnMessage(func(connection *websocket.Conn, message string) {
		commandMsg := CommandMsg{}
		err := commonhelper.JsonDecodeWithType(string(message), &commandMsg)
		if err != nil {
			connection.Close()
			return
		}
		switch commandMsg.Command {
		case COMMAND_INIT:
			initMsg := InitMsg{}
			err := commonhelper.JsonDecodeWithType(string(message), &initMsg)
			if err != nil {
				connection.Close()
				return
			}
			sid := initMsg.Sid
			transportServer.initConn(sid, connection)
			break
		case COMMAND_TRANSPORT:
			sid, err := transportServer.getConnSid(connection)
			if err != nil {
				connection.Close()
				return
			}
			transportMsg := TransportMsg{}
			err = commonhelper.JsonDecodeWithType(string(message), &transportMsg)

			if err != nil {
				connection.Close()
				return
			}
			targetConn, err := transportServer.getConnBySid(transportMsg.TargetSid)
			if err != nil {
				fmt.Println("目标隧道连接被关闭:" + transportMsg.TargetSid)
				return
			}
			sendToTunMsg := ClientMsgSendToTun{
				Command:  COMMAND_SEND_TO_TUN,
				Payload:  transportMsg.Payload,
				SrcSid:   sid,
				IsFinish: transportMsg.IsFinish,
			}
			err = targetConn.WriteJSON(sendToTunMsg)
			if err != nil {
				fmt.Println("发送到目标连接失败")
				return
			}

		}
	})
	fmt.Println("ws 转发服务启动:" + ":" + strconv.Itoa(listenPort) + "/transport")
	server.Start(listenPort, "transport", false, false)
}

func (transportServer *TransportServer) getConnSid(conn *websocket.Conn) (string, error) {
	if sid, ok := transportServer.initConnection.Load(conn); ok {
		return sid.(string), nil
	}
	return "", errors.New("unsafe connection")
}

func (transportServer *TransportServer) getConnBySid(sid string) (*websocket.Conn, error) {
	if conn, ok := transportServer.connectionMap.Load(sid); ok {
		return conn.(*websocket.Conn), nil
	}
	return nil, errors.New("unsafe connection")
}

func (transportServer *TransportServer) initConn(sid string, conn *websocket.Conn) {
	fmt.Println("接受到新的连接sid:" + sid)
	transportServer.initConnection.Store(conn, sid)
	transportServer.connectionMap.Store(sid, conn)
}
